package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/gin-gonic/gin"
	amqp "github.com/rabbitmq/amqp091-go"
)

// 处理错误，如果有错误则输出错误信息并终止程序
func failOnError(err error, msg string) {
	if err != nil {
		log.Panicf("%s: %s", msg, err)
	}
}

var ch *amqp.Channel // 声明一个全局变量用于存储 RabbitMQ 频道

// 初始化 RabbitMQ 连接和队列
func initmq() {
	// 连接到 RabbitMQ 服务器
	conn, err := amqp.DialConfig("amqp://testmq:testmq@127.0.0.1:5672/", amqp.Config{
		Heartbeat: 60 * time.Second, // 设置心跳间隔为 60 秒，防止连接超时
	})
	failOnError(err, "Failed to connect to RabbitMQ")

	// 创建一个通道
	ch, err = conn.Channel()
	failOnError(err, "Failed to open a channel")

	// 声明一个队列
	_, err = ch.QueueDeclare(
		"hello", // 队列名称
		true,    // 是否持久化
		false,   // 是否自动删除（当没有消费者时删除）
		false,   // 是否排他（仅当前连接可用）
		false,   // 等待服务器确认队列创建
		nil,     // 额外参数
	)
	failOnError(err, "Failed to declare a queue")

	// 监听 RabbitMQ 连接是否被关闭
	notifyClose := conn.NotifyClose(make(chan *amqp.Error))
	go func() {
		err := <-notifyClose
		if err != nil {
			fmt.Printf("连接关闭，心跳超时或其他原因: %v\n", err)
		} else {
			fmt.Println("连接正常关闭")
		}
	}()
}

func main() {
	initmq() // 初始化 RabbitMQ 连接
	//------------------------------------------------------------------------
	r := gin.New()                      // 创建 Gin 路由引擎
	r.GET("/mq", func(c *gin.Context) { // 定义一个 GET 请求的接口
		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) // 设置 5 秒的上下文超时
		defer cancel()

		body := "bodyFrom" // 消息内容
		err := ch.PublishWithContext(ctx,
			"",      // 交换机（此处为空，表示使用默认交换机）
			"hello", // 路由键（即队列名称）
			false,   // 是否强制投递（mandatory）
			false,   // 是否立即投递（immediate）
			amqp.Publishing{
				DeliveryMode: amqp.Persistent, // 设置消息持久化
				ContentType:  "text/plain",    // 消息内容类型
				Body:         []byte(body),    // 消息内容
			})
		failOnError(err, "Failed to publish a message") // 发送消息失败时打印错误信息
	})

	r.Run() // 启动 Gin 服务器
}
